package com.kate.mall.bff.wx.java8;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author 新梦想.陈超
 * @version 2021.2
 * @Description: {TODO}
 * @date 2023/3/13 下午4:26
 */

public class _04_Stream {
    public static void main(String[] args) {
        /*TODO 二、中间操作*/
        /*
        TODO 1. 筛选与切片
            filter( Predicate p)：接收Lambda，从流中排除某些元素
            distinct()：筛选，通过流所生成的hashCode()和equals()去除重复元素
            limit(long maxSize)：截断流，使其元素不超过给定数量
            skip(long n)：跳过元素，返回一个扔掉了前n个元素的流，若流中元素不足n个，则返回一个空流
         */
        List<Employee> employees = Arrays.asList(
                new Employee("张三", 18, 3333),
                new Employee("李四", 38, 55555),
                new Employee("王五", 50, 6666.66),
                new Employee("赵六", 16, 77777.77),
                new Employee("田七", 8, 8888.88)
        );
        Stream<Employee> stream = employees.stream();
        stream.filter((x) -> x.getAge() > 30)
                .limit(1)
                .forEach(System.out::println);

        test4();
        test5();
    }

    /*
       TODO 2.映射
           map接收Lambda，将元素转换成其它形式或提取信息，接收一个函数作为参数，该函数会被应用到每个元素上，并将其映射成一个新元素。flatMap 接收一个函数作为参数，将流中的每个值都转换成另一个流，然后把所有流连接成一个流。
   */
    public static void test2() {
        List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd");
        list.stream().map((x) -> x.toUpperCase()).forEach(System.out::println);
    }

    /*
    TODO 3.排序
        sorted()：自然排序
        sorted(Comparator com)：定制排序
     */
    public static void test3() {
        List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd");
        // 自然排序，按照字典进行排序
        list.stream().sorted().forEach(System.out::println);


        // 定制排序
        List<Employee> employees = Arrays.asList(
                new Employee("张三", 18, 3333),
                new Employee("李四", 38, 55555),
                new Employee("王五", 50, 6666.66),
                new Employee("赵六", 16, 77777.77),
                new Employee("田七", 8, 8888.88)
        );
        employees.stream().sorted((e1, e2) -> {
            if (e1.getAge() == e2.getAge()) {
                return e1.getName().compareTo(e2.getName());
            } else {
                return Integer.compare(e1.getAge(), e2.getAge());
            }
        }).forEach(System.out::println);
    }

    /*
    TODO 二、终止操作
        执行下列操作后，Stream流就会进行终止执行

     TODO 2.1   查找与匹配
        allMatch：检查是否匹配所有元素
        anyMatch：检查是否至少匹配一个元素
        noneMatch：检查是否一个都没匹配
        findFirst：返回第一个元素
        findAny：返回当前流中任意一个元素
        count：返回流中元素的个数
        max：返回当前流中最大值
        min：返回当前流中最小值
        forEach：内部迭代
     */

    public static void test4() {
        // 定制排序
        List<Employee> employees = Arrays.asList(
                new Employee("张三", 18, 3333),
                new Employee("李四", 38, 55555),
                new Employee("王五", 50, 6666.66),
                new Employee("赵六", 16, 77777.77),
                new Employee("田七", 8, 8888.88)
        );
        Boolean isAllMatch = employees.stream().allMatch((x) -> x.getAge() > 10);
        System.out.println("是否匹配所有元素:" + isAllMatch);

        Boolean isAnyMatch = employees.stream().anyMatch((x) -> x.getAge() > 10);
        System.out.println("是否匹配至少一个元素:" + isAnyMatch);
    }

    /*TODO 3.2.规约
        格式：reduce(T identity, BinaryOperator) / reduce(BinaryOperator)
        可以将流中元素反复结合，得到一个新值
        这个reduce，其实有点类似于Hadoop中的mapReduce，先做map操作，然后做reduce操作*/
    static void  test5() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        // 按照下面的规则进行累加操作
        // reduce的规约，就是把前面定义的起始值，作为了x
        Integer num = list.stream().reduce(0, (x, y) -> x + y);
        System.out.println(num);
    }
    /*TODO 3.3.收集

        Collection将流转换成其它形式，接收一个Collector接口实现，用于给Stream中元素做汇总的方法

        格式：collect(Collector c)

        Collector接口实现方法的实现决定了如何对流执行收集操作（如收集到List，Set，Map）。但是Collectors实用类提供了很多静态方法，可以方便地创建常用收集器实例*/
    /**
     * 收集器
     */
    public static void test6() {
        List<Employee> employees = Arrays.asList(
                new Employee("张三", 18, 3333),
                new Employee("李四", 38, 55555),
                new Employee("王五", 50, 6666.66),
                new Employee("赵六", 16, 77777.77),
                new Employee("田七", 8, 8888.88)
        );
        // 收集放入list中
        List<String> list = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toList());
        list.forEach(System.out::println);
    }
}
